package com.shenmazong.servernewsapi.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.shenmazong.*;
import com.shenmazong.servernewsapi.mapper.TbClickOkMapper;
import com.shenmazong.servernewsapi.mapper.TbServiceMapper;
import com.shenmazong.servernewsapi.mapper.TbUserImageMapper;
import com.shenmazong.servernewsapi.mapper.TbUserMapper;
import com.shenmazong.servernewsapi.service.NewsService;
import com.shenmazong.utils.ConstUtils;
import com.shenmazong.utils.ResponseResult;
import com.shenmazong.utils.UploadFileUtils;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.*;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;

@Service
@Slf4j
public class NewsServiceImpl implements NewsService {

    @Autowired
    TbServiceMapper tbServiceMapper;

    @Autowired
    TbClickOkMapper tbClickOkMapper;

    @Autowired
    TbUserMapper tbUserMapper;

    @Autowired
    TbUserImageMapper tbUserImageMapper;

    @Autowired
    RedisTemplate redisTemplate;

    /**
     * TODO 增加用户服务信息
     * @param userId
     * @param longitude
     * @param latitude
     * @param serviceType
     * @param Title
     * @param content
     * @return
     */
    @Override
    public ResponseResult addUserNews(Integer userId, Double longitude, Double latitude, Integer serviceType, String Title, String content) {
        ResponseResult result = ResponseResult.SUCCESS();

        //--1 写入数据库
        TbService news = new TbService();
        news.setUserid(userId);
        news.setLongitude(longitude);
        news.setLatitude(latitude);
        news.setServicetype(serviceType);
        news.setContent(content);

        tbServiceMapper.insert(news);

        //--2 写入到redis geo中
        RedisGeoCommands.GeoLocation<Integer> longGeoLocation = new RedisGeoCommands.GeoLocation<>(userId, new Point(longitude, latitude));
        redisTemplate.opsForGeo().add(ConstUtils.USER_GEO_ZSET_NAME, longGeoLocation);

        return result;
    }

    /**
     * TODO 删除用户信息
     * @param userId
     * @param newsId
     * @return
     */
    @Override
    public ResponseResult delUserNewsById(Integer userId, Integer newsId) {
        ResponseResult result = ResponseResult.SUCCESS();

        TbService news = tbServiceMapper.selectById(newsId);
        if(news == null) {
            result.setCode(-1);
            result.setMessage("信息不存在");
            return result;
        }

        if(!news.getUserid().equals(userId)) {
            result.setCode(-1);
            result.setMessage("没有删除权限");
            return result;
        }

        tbServiceMapper.deleteById(newsId);

        return result;
    }

    /**
     * TODO 修改用户服务信息
     * @param userId
     * @param newsId
     * @param longitude
     * @param latitude
     * @param serviceType
     * @param title
     * @param content
     * @return
     */
    @Override
    public ResponseResult setUserNews(Integer userId, Integer newsId, Double longitude, Double latitude, Integer serviceType, String title, String content) {
        ResponseResult result = ResponseResult.SUCCESS();

        //--1 检查新闻在不在
        TbService news = tbServiceMapper.selectById(newsId);
        if(news == null) {
            result.setCode(-1);
            result.setMessage("信息不存在");
            return result;
        }

        //--2 检查权限
        if(!news.getUserid().equals(userId)) {
            result.setCode(-1);
            result.setMessage("没有删除权限");
            return result;
        }

        //--3 修改信息
        news.setLongitude(longitude);
        news.setLatitude(latitude);
        news.setServicetype(serviceType);
        news.setTitle(title);
        news.setContent(content);
        tbServiceMapper.updateById(news);

        //--4 写入到redis geo中
        RedisGeoCommands.GeoLocation<Integer> longGeoLocation = new RedisGeoCommands.GeoLocation<>(userId, new Point(longitude, latitude));
        redisTemplate.opsForGeo().add(ConstUtils.USER_GEO_ZSET_NAME, longGeoLocation);

        return result;
    }

    /**
     * TODO 根据用户ID获取其服务信息列表
     * @param userId
     * @param pageNo
     * @param pageSize
     * @return
     */
    @Override
    public ResponseResult getNewsByUserId(Integer userId, Integer pageNo, Integer pageSize) {
        ResponseResult result = ResponseResult.SUCCESS();
        HashMap<String, Object> dataMap = new HashMap<>();

        //--1 分页信息
        Page<TbService> page = new Page<>(pageNo, pageSize);

        //--2 设置查询条件
        QueryWrapper<TbService> queryWrapper = new QueryWrapper<>();
        // where userid=2
        queryWrapper.eq("userid", userId);
        // order by id desc
        queryWrapper.orderByDesc("id");

        //--3 信息查询
        IPage<TbService> iPage = tbServiceMapper.selectPage(page, queryWrapper);
        if(iPage == null) {
            result.setCode(-1);
            result.setMessage("没有数据");
            return result;
        }

        //--4 设置返回数据
//        Long currentPage = iPage.getCurrent();
//        long pages = iPage.getPages();
//        long total = iPage.getTotal();
        //iPage.getRecords()

        dataMap.put("page", iPage);

        result.setResult(dataMap);

        return result;
    }

    /**
     * TODO 根据新闻的类型，获取新闻
     * @param userId
     * @param typeId
     * @param pageNo
     * @param pageSize
     * @return
     */
    @Override
    public ResponseResult getNewsByTypeId(Integer userId, Integer typeId, Integer pageNo, Integer pageSize) {
        ResponseResult result = ResponseResult.SUCCESS();
        HashMap<String, Object> dataMap = new HashMap<>();

        //--1 分页信息
        Page<TbService> page = new Page<>(pageNo, pageSize);

        //--2 设置查询条件
        QueryWrapper<TbService> queryWrapper = new QueryWrapper<>();
        // where userid=2
        queryWrapper.eq("servicetype", typeId);
        // order by id desc
        queryWrapper.orderByDesc("id");

        //--3 信息查询
        IPage<TbService> iPage = tbServiceMapper.selectPage(page, queryWrapper);
        if(iPage == null) {
            result.setCode(-1);
            result.setMessage("没有数据");
            return result;
        }

        //--4 设置返回数据
//        Long currentPage = iPage.getCurrent();
//        long pages = iPage.getPages();
//        long total = iPage.getTotal();
        //iPage.getRecords()

        dataMap.put("page", iPage);

        result.setResult(dataMap);

        return result;
    }

    /**
     * TODO 根据位置获取周边服务
     * @param userId
     * @param longitude
     * @param latitude
     * @param distance
     * @return
     */
    @Override
    public ResponseResult getNewsByCircle(Integer userId, Double longitude, Double latitude, Long distance) {
        ResponseResult result = ResponseResult.SUCCESS();
        HashMap<String, Object> dataMap = new HashMap<>();

        //--1 定义范围
        Point center = new Point(longitude,latitude);
        Distance radius = new Distance(distance);
        Circle circle = new Circle(center, radius);

        //--2 查找用户
        List<Integer> ids = new ArrayList<>();
        GeoResults<RedisGeoCommands.GeoLocation<Integer>> users = redisTemplate.opsForGeo().radius(ConstUtils.USER_GEO_ZSET_NAME, circle);
        List<GeoResult<RedisGeoCommands.GeoLocation<Integer>>> contents = users.getContent();
        contents.forEach(content->{
            //log.info(content);
            RedisGeoCommands.@NonNull GeoLocation<Integer> user = content.getContent();
            Integer uid = user.getName();
            ids.add(uid);
            log.info("userid="+user.getName());
        });

        //--3 循环查找用户
        List<TbService> tbServices = tbServiceMapper.selectBatchIds(ids);
        if(tbServices == null) {
            result.setCode(-1);
            result.setMessage("没有数据");
            return result;
        }

        dataMap.put("users", tbServices);
        result.setResult(dataMap);

        return result;
    }

    /**
     * TODO 根据关键字搜索服务信息
     * @param keyWord
     * @return
     */
    @Override
    public ResponseResult getNewsByKeyword(String keyWord) {
        ResponseResult result = ResponseResult.FAIL();
        return result;
    }

    /**
     * TODO 实现点赞(MySQL)
     * @param userId
     * @param newId
     * @return
     */
    @Override
    public ResponseResult doClickOk(Integer userId, Integer newId) {
        ResponseResult result = ResponseResult.FAIL();
        HashMap<String, Object> dataMap = new HashMap<>();

        //--1 是否已经点赞，如果已经点赞则取消
        TbClickOk tbClickOk = tbClickOkMapper.selectOne(new QueryWrapper<TbClickOk>()
                .eq("userid", userId)
                .eq("newsid", newId)
                .last("limit 1"));
        if(tbClickOk != null) {
            // 取消点赞
            tbClickOkMapper.delete(new QueryWrapper<TbClickOk>()
                    .eq("userid", userId)
                    .eq("newsid", newId));
            // 更新点赞总数
            TbService tbService = tbServiceMapper.selectById(newId);
            tbService.setClicks(tbService.getClicks()-1);
            tbServiceMapper.updateById(tbService);

            dataMap.put("newId", newId);
            dataMap.put("clicks", tbService.getClicks());

            result.setResult(dataMap);
            return result;
        }

        //--2 用户是否存在
        TbUser tbUser = tbUserMapper.selectById(userId);
        if(tbUser == null) {
            result.setCode(-1);
            result.setMessage("没有此用户信息");
            return result;
        }

        //--3 文章是否存在
        TbService tbService = tbServiceMapper.selectById(newId);
        if(tbService == null) {
            result.setCode(-1);
            result.setMessage("没有服务信息");
            return result;
        }

        //--4 增加点赞信息
        TbClickOk tbClickOk1 = new TbClickOk();
        tbClickOk1.setUserid(userId);
        tbClickOk1.setNewsid(newId);
        tbClickOkMapper.insert(tbClickOk1);

        //--5 修改点赞总数
        tbService.setClicks(tbService.getClicks()+1);
        tbServiceMapper.updateById(tbService);

        dataMap.put("newId", newId);
        dataMap.put("clicks", tbService.getClicks());

        result.setResult(dataMap);
        return result;
    }

    /**
     * TODO 实现点赞(Redis)
     * @param userId
     * @param newId
     * @return
     */
    @Override
    public ResponseResult doClickOkQuick(Integer userId, Integer newId) {
        ResponseResult result = ResponseResult.FAIL();
        HashMap<String, Object> dataMap = new HashMap<>();

        //--1 是否点赞
        // 用新闻id做key，userid做value
        String key = "click_ok_" + newId;
        Boolean isExists = redisTemplate.opsForSet().isMember(key, userId);
        if(isExists) {
            // 取消点赞
            redisTemplate.opsForSet().remove(key, userId);

            dataMap.put("newId", newId);
            dataMap.put("clicks", redisTemplate.opsForSet().size(key));

            result.setResult(dataMap);
            return result;
        }

        //--2 执行点赞
        redisTemplate.opsForSet().add(key, userId);

        dataMap.put("newId", newId);
        dataMap.put("clicks", redisTemplate.opsForSet().size(key));

        result.setResult(dataMap);
        return result;
    }

    @Override
    public ResponseResult uploadNewsImage(Integer userId, MultipartFile file) {
        ResponseResult result = ResponseResult.SUCCESS();
        HashMap<String, Object> dataMap = new HashMap<>();

        //--1 验证用户是否存在
        TbUser user = tbUserMapper.selectById(userId);
        if(user == null) {
            result.setCode(-1);
            result.setMessage("获取用户信息失败");
            return result;
        }

        //--2 上传文件
        if(file.isEmpty()){
            log.info("上传文件为空");
            result.setCode(-1);
            result.setMessage("上传文件为空");
            return result;
        }
        String fileName = file.getOriginalFilename();
        int size = (int) file.getSize();
        log.info(fileName + "-->" + size);

        UUID uuid = UUID.randomUUID();
        String suffix = fileName.substring(fileName.lastIndexOf(".")).toLowerCase();
        String newName = uuid.toString() + suffix;
        String imageUrl = UploadFileUtils.uploadAliyunOss(file, newName);
        if(imageUrl == null) {
            result.setCode(-1);
            result.setMessage("上传文件到OSS失败");
            return result;
        }

        //--3 记录用户上传图片
        TbUserImage tbUserImage = new TbUserImage();
        tbUserImage.setUserid(userId);
        tbUserImage.setImageurl(imageUrl);
        tbUserImageMapper.insert(tbUserImage);

        dataMap.put("userId", userId);
        dataMap.put("imageurl", imageUrl);

        result.setResult(dataMap);
        return result;
    }
}
